home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Mail
/
pine3.92
/
pico
/
dos_gen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-14
|
16KB
|
775 lines
/*
* $Id: dos_gen.c,v 4.19 1996/03/15 07:41:11 hubert Exp $
*
* Program: Operating system dependent routines - MS DOS Generic
*
*
* Michael Seibel
* Networks and Distributed Computing
* Computing and Communications
* University of Washington
* Administration Builiding, AG-44
* Seattle, Washington, 98195, USA
* Internet: mikes@cac.washington.edu
*
* Please address all bugs and comments to "pine-bugs@cac.washington.edu"
*
*
* Pine and Pico are registered trademarks of the University of Washington.
* No commercial use of these trademarks may be made without prior written
* permission of the University of Washington.
*
* Pine, Pico, and Pilot software and its included text are Copyright
* 1989-1996 by the University of Washington.
*
* The full text of our legal notices is contained in the file called
* CPYRIGHT, included with this distribution.
*
*
* Notes:
* - This file should contain the cross section of functions useful
* in both DOS and Windows ports of pico.
*
*/
#ifdef WIN32
#include <io.h>
#endif
/*
* picosigs - Install any handlers for the signals we're interested
* in catching.
*/
picosigs()
{
/* no op */
}
/*
* Useful definitions...
*/
#ifdef MOUSE
static int mexist = 0; /* is the mouse driver installed? */
static int nbuttons; /* number of buttons on the mouse */
static unsigned mnoop;
#endif
static unsigned char okinfname[32] = {
0, 0, /* ^@ - ^G, ^H - ^O */
0, 0, /* ^P - ^W, ^X - ^_ */
0x80, 0x17, /* SP - ' , ( - / */
0xff, 0xe0, /* 0 - 7 , 8 - ? */
0x7f, 0xff, /* @ - G , H - O */
0xff, 0xe9, /* P - W , X - _ */
0x7f, 0xff, /* ` - g , h - o */
0xff, 0xf6, /* p - w , x - DEL */
0, 0, /* > DEL */
0, 0, /* > DEL */
0, 0, /* > DEL */
0, 0, /* > DEL */
0, 0 /* > DEL */
};
/*
* fallowc - returns TRUE if c is allowable in filenames, FALSE otw
*/
fallowc(c)
int c;
{
return(okinfname[c>>3] & 0x80>>(c&7));
}
#ifdef MOUSE
/*
* end_mouse - a no-op on DOS/Windows
*/
void
end_mouse()
{
}
/*
* mouseexist - function to let outsiders know if mouse is turned on
* or not.
*/
mouseexist()
{
return(mexist);
}
#endif /* MOUSE */
/*
* fexist - returns TRUE if the file exists, FALSE otherwise
*/
fexist(file, m, l)
char *file, *m;
long *l;
{
struct stat sbuf;
if(l != NULL)
*l = 0L;
if(stat(file, &sbuf) < 0){
if(errno == ENOENT) /* File not found */
return(FIOFNF);
else
return(FIOERR);
}
if(l != NULL)
*l = sbuf.st_size;
if(sbuf.st_mode & S_IFDIR)
return(FIODIR);
else if(*m == 't') /* no links, just say yes */
return(FIOSUC);
if(m[0] == 'r') /* read access? */
return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD);
else if(m[0] == 'w') /* write access? */
return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT);
else if(m[0] == 'x') /* execute access? */
return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX);
return(FIOERR); /* what? */
}
/*
* isdir - returns true if fn is a readable directory, false otherwise
* silent on errors (we'll let someone else notice the problem;)).
*/
isdir(fn, l)
char *fn;
long *l;
{
struct stat sbuf;
if(l)
*l = 0;
if(stat(fn, &sbuf) < 0)
return(0);
if(l)
*l = sbuf.st_size;
return(sbuf.st_mode & S_IFDIR);
}
/*
* gethomedir - returns the users home directory
* Note: home is malloc'd for life of pico
*/
char *gethomedir(l)
int *l;
{
static char *home = NULL;
static short hlen = 0;
if(home == NULL){
char buf[NLINE];
sprintf(buf, "%c:\\", _getdrive() + 'A' - 1);
hlen = strlen(buf);
if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){
emlwrite("Problem allocating space for home dir", NULL);
return(0);
}
strcpy(home, buf);
}
if(l)
*l = hlen;
return(home);
}
/*
* homeless - returns true if given file does not reside in the current
* user's home directory tree.
*/
homeless(f)
char *f;
{
char *home;
int len;
home = gethomedir(&len);
return(strncmp(home, f, len));
}
/*
* errstr - return system error string corresponding to given errno
* Note: strerror() is not provided on all systems, so it's
* done here once and for all.
*/
char *errstr(err)
int err;
{
return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
}
/*
* getfnames - return all file names in the given directory in a single
* malloc'd string. n contains the number of names
*/
char *getfnames(dn, pat, n, e)
char *dn, *pat, *e;
int *n;
{
int status;
long l;
char *names, *np, *p;
char buf[NLINE];
struct stat sbuf;
#ifdef WIN32
struct _finddata_t dbuf;
long findrv;
#else
struct find_t dbuf; /* opened directory */
#endif
*n = 0;
if(stat(dn, &sbuf) < 0){
if(e)
sprintf(e, "\007Dir \"%s\": %s", dn, strerror(errno));
return(NULL);
}
else{
l = sbuf.st_size;
if(!(sbuf.st_mode & S_IFDIR)){
if(e)
sprintf(e, "\007Not a directory: \"%s\"", dn);
return(NULL);
}
}
if((names=(char *)malloc(sizeof(char)*3072)) == NULL){
if(e)
sprintf(e, "\007Can't malloc space for file names", NULL);
return(NULL);
}
np = names;
strcpy(buf, dn);
sprintf(buf, "%s%s%s*%s%s", dn,
(dn[strlen(dn)-1] == '\\') ? "\\" : "",
(pat && *pat) ? pat : "",
(pat && *pat && strchr(pat, '.')) ? "" : ".",
(pat && *pat && strchr(pat, '.')) ? "" : "*");
#ifdef WIN32
if((findrv = _findfirst(buf, &dbuf)) < 0){
#else
if(_dos_findfirst(buf, _A_NORMAL|_A_SUBDIR, &dbuf) != 0){
#endif
if(e)
sprintf(e, "Can't find first file in \"%s\"", dn);
free((char *) names);
return(NULL);
}
do{
(*n)++;
p = dbuf.name;
while((*np++ = *p++) != '\0')
;
}
#ifdef WIN32
while(_findnext(findrv, &dbuf) == 0);
_findclose(findrv);
#else
while(_dos_findnext(&dbuf) == 0);
#endif
return(names);
}
/*
* fioperr - given the error number and file name, display error
*/
void
fioperr(e, f)
int e;
char *f;
{
switch(e){
case FIOFNF: /* File not found */
emlwrite("\007File \"%s\" not found", f);
break;
case FIOEOF: /* end of file */
emlwrite("\007End of file \"%s\" reached", f);
break;
case FIOLNG: /* name too long */
emlwrite("\007File name \"%s\" too long", f);
break;
case FIODIR: /* file is a directory */
emlwrite("\007File \"%s\" is a directory", f);
break;
case FIONWT:
emlwrite("\007Write permission denied: %s", f);
break;
case FIONRD:
emlwrite("\007Read permission denied: %s", f);
break;
case FIONEX:
emlwrite("\007Execute permission denied: %s", f);
break;
default:
emlwrite("\007File I/O error: %s", f);
}
}
/*
* pfnexpand - pico's function to expand the given file name if there is
* a leading '~'
*/
char *pfnexpand(fn, len)
char *fn;
int len;
{
return(fn);
}
/*
* fixpath - make the given pathname into an absolute path
*/
fixpath(name, len)
char *name;
int len;
{
char file[_MAX_PATH];
int dr;
if(!len)
return(0);
/* return the full path of given file */
if(isalpha(name[0]) && name[1] == ':'){ /* have drive spec? */
if(name[2] != '\\'){ /* including path? */
dr = toupper(name[0]) - 'A' + 1;
if(_getdcwd(dr, file, _MAX_PATH) != NULL){
if(file[strlen(file)-1] != '\\')
strcat(file, "\\");
strcat(file, &name[2]); /* add file name */
}
else
return(0);
}
else
return(1); /* fully qualified with drive and path! */
}
else if(name[0] == '\\') { /* no drive spec! */
sprintf(file, "%c:%s", _getdrive()+'A'-1, name);
}
else{
if(Pmaster && !gmode&MDCURDIR)
strcpy(file, gmode&MDTREE ? opertree : gethomedir(NULL));
else if(!_getcwd(file, _MAX_PATH)) /* no qualification */
return(0);
if(*name){ /* if name, append it */
strcat(file, "\\");
strcat(file, name);
}
}
strncpy(name, file, len); /* copy back to real buffer */
name[len-1] = '\0'; /* tie off just in case */
return(1);
}
/*
* compresspath - given a base path and an additional directory, collapse
* ".." and "." elements and return absolute path (appending
* base if necessary).
*
* returns 1 if OK,
* 0 if there's a problem
* new path, by side effect, if things went OK
*/
compresspath(base, path, len)
char *base, *path;
int len;
{
register int i;
int depth = 0;
char *p;
char *stack[32];
char pathbuf[NLINE];
#define PUSHD(X) (stack[depth++] = X)
#define POPD() ((depth > 0) ? stack[--depth] : "")
strcpy(pathbuf, path);
fixpath(pathbuf, len);
p = pathbuf;
for(i=0; pathbuf[i] != '\0'; i++){ /* pass thru path name */
if(pathbuf[i] == C_FILESEP){
if(p != pathbuf)
PUSHD(p); /* push dir entry */
p = &pathbuf[i+1]; /* advance p */
pathbuf[i] = '\0'; /* cap old p off */
continue;
}
if(pathbuf[i] == '.'){ /* special cases! */
if(pathbuf[i+1] == '.' /* parent */
&& (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){
if(!strcmp(POPD(),"")) /* bad news! */
return(0);
i += 2;
p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
}
else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){
i++;
p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
}
}
}
if(*p != '\0')
PUSHD(p); /* get last element */
path[0] = '\0';
for(i = 0; i < depth; i++){
strcat(path, S_FILESEP);
strcat(path, stack[i]);
}
return(1); /* everything's ok */
}
/*
* tmpname - return a temporary file name in the given buffer
*/
void
tmpname(name)
char *name;
{
sprintf(name, "%s.txt", tempnam(getenv("TEMP"), "ae"));
}
/*
* Take a file name, and from it
* fabricate a buffer name. This routine knows
* about the syntax of file names on the target system.
* I suppose that this information could be put in
* a better place than a line of code.
*/
void
makename(bname, fname)
char bname[];
char fname[];
{
register char *cp1;
register char *cp2;
cp1 = &fname[0];
while (*cp1 != 0)
++cp1;
while (cp1!=&fname[0] && cp1[-1]!='\\')
--cp1;
cp2 = &bname[0];
while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
*cp2++ = *cp1++;
*cp2 = 0;
}
/*
* copy - copy contents of file 'a' into a file named 'b'. Return error
* if either isn't accessible or is a directory
*/
copy(a, b)
char *a, *b;
{
int in, out, n, rv = 0;
char *cb;
struct stat tsb, fsb;
if(stat(a, &fsb) < 0){ /* get source file info */
emlwrite("Can't Copy: %s", errstr(errno));
return(-1);
}
if(!(fsb.st_mode&S_IREAD)){ /* can we read it? */
emlwrite("\007Read permission denied: %s", a);
return(-1);
}
if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
emlwrite("\007Can't copy: %s is a directory", a);
return(-1);
}
if(stat(b, &tsb) < 0){ /* get dest file's mode */
switch(errno){
case ENOENT:
break; /* these are OK */
default:
emlwrite("\007Can't Copy: %s", errstr(errno));
return(-1);
}
}
else{
if(!(tsb.st_mode&S_IWRITE)){ /* can we write it? */
emlwrite("\007Write permission denied: %s", b);
return(-1);
}
if((tsb.st_mode&S_IFMT) == S_IFDIR){ /* is it directory? */
emlwrite("\007Can't copy: %s is a directory", b);
return(-1);
}
if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
emlwrite("\007Identical files. File not copied", NULL);
return(-1);
}
}
if((in = open(a, _O_RDONLY)) < 0){
emlwrite("Copy Failed: %s", errstr(errno));
return(-1);
}
if((out=creat(b, fsb.st_mode&0xfff)) < 0){
emlwrite("Can't Copy: %s", errstr(errno));
close(in);
return(-1);
}
if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
emlwrite("Can't allocate space for copy buffer!", NULL);
close(in);
close(out);
return(-1);
}
while(1){ /* do the copy */
if((n = read(in, cb, NLINE)) < 0){
emlwrite("Can't Read Copy: %s", errstr(errno));
rv = -1;
break; /* get out now */
}
if(n == 0) /* done! */
break;
if(write(out, cb, n) != n){
emlwrite("Can't Write Copy: %s", errstr(errno));
rv = -1;
break;
}
}
free(cb);
close(in);
close(out);
return(rv);
}
/*
* Open a file for writing. Return TRUE if all is well, and FALSE on error
* (cannot create).
*/
ffwopen(fn)
char *fn;
{
extern FILE *ffp;
if ((ffp=fopen(fn, "w")) == NULL) {
emlwrite("Cannot open file for writing", NULL);
return (FIOERR);
}
return (FIOSUC);
}
/*
* Close a file. Should look at the status in all systems.
*/
ffclose()
{
extern FILE *ffp;
if (fclose(ffp) != FALSE) {
emlwrite("Error closing file", NULL);
return(FIOERR);
}
return(FIOSUC);
}
/*
* worthit - generic sort of test to roughly gage usefulness of using
* optimized scrolling.
*
* note:
* returns the line on the screen, l, that the dot is currently on
*/
worthit(l)
int *l;
{
int i; /* l is current line */
unsigned below; /* below is avg # of ch/line under . */
*l = doton(&i, &below);
below = (i > 0) ? below/(unsigned)i : 0;
return(below > 3);
}
/*
* o_insert - optimize screen insert of char c
*/
o_insert(c)
char c;
{
return(0);
}
/*
* o_delete - optimized character deletion
*/
o_delete()
{
return(0);
}
/*
* pico_new_mail - just checks mtime and atime of mail file and notifies user
* if it's possible that they have new mail.
*/
pico_new_mail()
{
return(0);
}
/*
* time_to_check - checks the current time against the last time called
* and returns true if the elapsed time is > timeout
*/
time_to_check()
{
static time_t lasttime = 0L;
if(!timeout)
return(FALSE);
if(time((long *) 0) - lasttime > (time_t)timeout){
lasttime = time((long *) 0);
return(TRUE);
}
else
return(FALSE);
}
/*
* sstrcasecmp - compare two pointers to strings case independently
*/
sstrcasecmp(s1, s2)
QcompType *s1, *s2;
{
return(stricmp(*(char **)s1, *(char **)s2));
}
/*
* chkptinit -- initialize anything we need to support composer
* checkpointing
*/
chkptinit(file, n)
char *file;
int n;
{
if(!file[0]){
long gmode_save = gmode;
if(gmode&MDCURDIR)
gmode &= ~MDCURDIR; /* so fixpath will use home dir */
strcpy(file, "#picoTM0.txt");
fixpath(file, NLINE);
gmode = gmode_save;
}
else{
int l = strlen(file);
if(file[l-1] != '\\'){
file[l++] = '\\';
file[l] = '\0';
}
strcpy(file + l, "#picoTM0.txt");
}
if(fexist(file, "r", NULL) == FIOSUC){ /* does file exist? */
char copy[NLINE];
strcpy(copy, "#picoTM1.txt");
fixpath(copy, NLINE);
rename(file, copy); /* save so we don't overwrite it */
}
unlink(file);
}
/*
* sleep the given number of microseconds
*/
ssleep(s)
clock_t s;
{
s += clock();
while(s > clock())
;
}
/*
* sleep the given number of seconds
*/
sleep(t)
int t;
{
time_t out = (time_t)t + time((long *) 0);
while(out > time((long *) 0))
;
}